package cn.seaboot.admin.net.manager;

import cn.seaboot.commons.http.HttpException;
import cn.seaboot.commons.http.HttpRequest;
import cn.seaboot.commons.http.HttpStatusException;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.jetbrains.annotations.NotNull;
import org.springframework.web.client.HttpStatusCodeException;

import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * 请求工具
 *
 * @author Mr.css
 * @version 2025-02-14 11:59
 */
public class HttpClientUtils {


    /**
     * 检测请求状态
     *
     * @param response 请求体
     */
    public static void checkStatus(ClassicHttpResponse response) {
        int code = response.getCode();
        if (code != HttpStatus.SC_OK) {
            throw new HttpStatusException("Error status :" + code);
        }
    }

    /**
     * 复制 {@link HttpServletRequest} 中的所有参数和请求头，构建出一个新的请求，这个函数一般用于转发
     *
     * @param src 请求参数
     */
    public static HttpRequest forward(CloseableHttpClient httpClient, @NotNull HttpServletRequest src, String target) {
        URI uri = URI.create(target + src.getServletPath() + src.getQueryString());
        src.getContentType();
        if ("GET".equals(src.getMethod())) {
            HttpRequest req = new HttpRequest(httpClient, src.getMethod(), uri);
            HttpClientUtils.copyFullHeader(src, req);
            return req;
        } else if ("POST".equals(src.getMethod())) {
            HttpRequest req = new HttpRequest(httpClient, src.getMethod(), uri);
            HttpClientUtils.copyFullHeader(src, req);
            List<NameValuePair> params = HttpClientUtils.getParameters(src);
            if (!params.isEmpty()) {
                req.setEntity(new UrlEncodedFormEntity(params, Charset.defaultCharset()));
            }
            return req;
        } else if ("PUT".equals(src.getMethod())) {
            HttpRequest req = new HttpRequest(httpClient, src.getMethod(), uri);
            HttpClientUtils.copyFullHeader(src, req);
            return req;
        } else if ("DELETE".equals(src.getMethod())) {
            HttpRequest req = new HttpRequest(httpClient, src.getMethod(), uri);
            HttpClientUtils.copyFullHeader(src, req);
            return req;
        } else {
            throw new HttpException("Unsupported method: " + src.getMethod());
        }
    }


    /**
     * 复制 {@link HttpServletRequest} 中的所有参数和请求头，构建出一个新的请求，这个函数一般用于转发
     * <p>
     * 以 post 方式提交 restful 风格的表单
     *
     * @param src 请求参数
     */
    public static HttpRequest forwardAsPost(CloseableHttpClient httpClient, @NotNull HttpServletRequest src, String target) {
        URI uri = URI.create(target + src.getServletPath() + src.getQueryString());
        if ("GET".equals(src.getMethod())) {
            HttpRequest get = new HttpRequest(httpClient, src.getMethod(), uri);
            HttpClientUtils.copyFullHeader(src, get);
            return get;
        } else {
            // 对于 restful 风格的请求，有些系统支持用 post 方式提交表单
            HttpRequest post = new HttpRequest(httpClient, src.getMethod(), uri);
            HttpClientUtils.copyFullHeader(src, post);
            List<NameValuePair> params = HttpClientUtils.getParameters(src);
            params.add(new BasicNameValuePair("_method", src.getMethod().toLowerCase()));
            post.setEntity(new UrlEncodedFormEntity(params, Charset.defaultCharset()));
            return post;
        }
    }


    /**
     * 复制请求头中的所有内容
     *
     * @param src servlet-request
     * @param ret client-request
     */
    public static void copyFullHeader(HttpServletRequest src, HttpRequest ret) {
        Enumeration<String> headerNames = src.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            Enumeration<String> headers = src.getHeaders(headerName);
            while (headers.hasMoreElements()) {
                ret.setHeader(headerName, headers.nextElement());
            }
        }
    }


    /**
     * 获取请求域中的所有参数
     *
     * @param request 请求域
     * @return 键值对
     */
    public static List<NameValuePair> getParameters(HttpServletRequest request) {
        Enumeration<String> params = request.getParameterNames();
        List<NameValuePair> pairList = new ArrayList<>();
        while (params.hasMoreElements()) {
            String paramName = params.nextElement();
            String[] values = request.getParameterValues(paramName);
            for (String value : values) {
                pairList.add(new BasicNameValuePair(paramName, value));
            }
        }
        return pairList;
    }
}
